import { _decorator, v2, Vec2 } from 'cc';

export namespace Bezier {

    export enum BezierType { 
        LINEAR = 2, // 线性
        QUADRATIC = 3, // 二次贝塞尔曲线
        CUBIC = 4, // 三次贝塞尔曲线
    }

    /**
     * 将点数组转换为贝塞尔曲线
     * @param points 点数组，格式为 [Vec2, Vec2, ...]
     * @param segmentLength 每段贝塞尔曲线的控制点数量（默认 4，表示三次贝塞尔曲线）
     * @returns 贝塞尔曲线上的点数组
     */
    export function pointsToBezierCurve(points: Vec2[], segmentLength: BezierType = 3, pointsPerUnit: number = 1): Vec2[] {
        const curvePoints: Vec2[] = [];
        const totalPoints = points.length;

        // 动态分段处理
        for (let i = 0; i < totalPoints - 1; i += segmentLength - 1) {
            const controlPoints = points.slice(i, i + segmentLength);

            // 如果当前段的控制点数量不足，则补全
            if (controlPoints.length < segmentLength) {
                while (controlPoints.length < segmentLength) {
                    controlPoints.push(controlPoints[controlPoints.length - 1]);
                }
            }

            // 计算当前段的总距离
            let totalDistance = 0;
            for (let j = 1; j < controlPoints.length; j++) {
                totalDistance += controlPoints[j].clone().subtract(controlPoints[j - 1]).length();
            }

            // 动态调整步长
            const step = 1 / (totalDistance * pointsPerUnit);

            // 生成当前段的贝塞尔曲线
            const segmentCurve = generateBezierSegment(controlPoints, step);
            curvePoints.push(...segmentCurve);
        }

        return curvePoints;
    }
    /**
     * 生成一段贝塞尔曲线
     * @param controlPoints 控制点数组
     * @param step 步长（决定曲线的平滑度，默认 0.01）
     * @returns 贝塞尔曲线上的点数组
     */
    function generateBezierSegment(controlPoints: Vec2[], step: number = 0.01): Vec2[] {
        const curvePoints: Vec2[] = [];
        const n = controlPoints.length - 1; // 控制点数量减 1

        for (let t = 0; t <= 1; t += step) {
            let x = 0;
            let y = 0;

            // 计算贝塞尔曲线上的点
            for (let i = 0; i <= n; i++) {
                const binomialCoefficient = getBinomialCoefficient(n, i);
                const term = binomialCoefficient * Math.pow(1 - t, n - i) * Math.pow(t, i);
                x += controlPoints[i].x * term;
                y += controlPoints[i].y * term;
            }

            curvePoints.push(v2(x, y));
        }

        return curvePoints;
    }

    /**
     * 计算二项式系数（组合数）
     * @param n 总数
     * @param k 选取数
     * @returns 二项式系数值
     */
    function getBinomialCoefficient(n: number, k: number): number {
        if (k < 0 || k > n) return 0;
        if (k === 0 || k === n) return 1;

        let result = 1;
        for (let i = 1; i <= k; i++) {
            result *= (n - k + i) / i;
        }

        return result;
    }


}
